﻿#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include "Common.hpp"



// 直接去堆上按⻚申请空间
//inline static void* SystemAlloc(size_t kpage)
//{
//#ifdef _WIN32
//	void* ptr = VirtualAlloc(0, kpage * (8*1024), MEM_COMMIT | MEM_RESERVE,
//		PAGE_READWRITE);
//#else
//	// linux下brk mmap等
//#endif
//	if (ptr == nullptr)
//		throw std::bad_alloc();
//	return ptr;
//}
template<class T>
class ObjectPool
{
public:

	T* New()
	{
		//如果链表不为空先使用链表中的空间,重复利用
		T* obj = nullptr;
		if (_freelist != nullptr)
		{
			obj = (T*)_freelist;
			_freelist = *(void**)_freelist;
		}
		else
		{
			//剩余空间不够一个T的大小
			if (_remainBytes < sizeof(T))
			{
				_remainBytes = 128 * 1024;
				//_memory = (char*)malloc(128 * 1024);
				//按页分配,每页8kb
				_memory = (char*)SystemAlloc(_remainBytes>>13);
				if (_memory == nullptr)
					throw bad_alloc();

			}

			obj = (T*)_memory;
			if (obj == nullptr)
			{
				int x = 0;
			}
			//T类型比指针大小还小
			size_t objsize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
			_memory += objsize;
			_remainBytes -= objsize;
		}
		//定位new，显式调用T的构造函数

		new(obj)T;

		return obj;
	}

	void Delete(T* obj)
	{
		//显示调用析构清理对象
		obj->~T();
		//不找尾了，直接头插
		*(void**)obj = _freelist;
		_freelist = obj;

	}
private:
	char* _memory = nullptr;//申请的大块空间
	size_t _remainBytes = 0;//剩余字节数
	void* _freelist = nullptr;//还回来的空间链表
};

//
//struct TreeNode
//{
//	int _val;
//	TreeNode* _left;
//	TreeNode* _right;
//	TreeNode()
//		:_val(0)
//		, _left(nullptr)
//		, _right(nullptr)
//	{}
//};
//void TestObjectPool()
//{
//	// 申请释放的轮次
//	const size_t Rounds = 3;
//	// 每轮申请释放多少次
//	const size_t N = 100000;
//	size_t begin1 = clock();
//	std::vector<TreeNode*> v1;
//	v1.reserve(N);
//	for (size_t j = 0; j < Rounds; ++j)
//	{
//		for (int i = 0; i < N; ++i)
//		{
//			v1.push_back(new TreeNode);
//		}
//		for (int i = 0; i < N; ++i)
//		{
//			delete v1[i];
//		}
//		v1.clear();
//	}
//	size_t end1 = clock();
//	ObjectPool<TreeNode> TNPool;
//	size_t begin2 = clock();
//	std::vector<TreeNode*> v2;
//	v2.reserve(N);
//	for (size_t j = 0; j < Rounds; ++j)
//	{
//		for (int i = 0; i < N; ++i)
//		{
//			v2.push_back(TNPool.New());
//		}
//		for (int i = 0; i < 100000; ++i)
//		{
//			TNPool.Delete(v2[i]);
//		}
//		v2.clear();
//	}
//	size_t end2 = clock();
//	cout << "new cost time:" << end1 - begin1 << endl;
//	cout << "object pool cost time:" << end2 - begin2 << endl;
//}
